using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.IO;
using LibNDSFormats.NSBMD;
using Tao.OpenGl;
using LibNDSFormats.NSBTX;
using Tao.FreeGlut;
using Tao.Ode;
using System.Windows.Forms.VisualStyles;

namespace MKDS_Course_Editor
{
    public partial class nsbmd : Form
    {
        string file_2 = "";
        string file_3 = "";
        byte[] file_;
        byte[] tex;
        Nsbmd nsbm;
        NsbmdGlRenderer t;
        Nsbmd nsbm2;
        NsbmdGlRenderer t2;
        NSBCA.NSBCA.NSBCA_File ca;
        public nsbmd(string file)
        {
            file_2 = file;
            file_ = File.ReadAllBytes(file);
            InitializeComponent();
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }
        public nsbmd(byte[] file, byte[] texture)
        {
            file_ = file;
            tex = texture;
            InitializeComponent();
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }
        public nsbmd(byte[] file, byte[] texture, string file2, string file3)
        {
            file_2 = file2;
            file_3 = file3;
            file_ = file;
            tex = texture;
            InitializeComponent();
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }
        public nsbmd(byte[] file)
        {
            file_ = file;

            InitializeComponent();
            simpleOpenGlControl1.InitializeContexts();
            simpleOpenGlControl1.MouseWheel += new MouseEventHandler(simpleOpenGlControl1_MouseWheel);
        }
        void simpleOpenGlControl1_MouseWheel(object sender, MouseEventArgs e)
        {
			if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
			{
				dist += (float)e.Delta / 100;
			}
			else
			{
				dist += (float)e.Delta / 1000;
			}
            RenderFunc1(nsbm, t);
            simpleOpenGlControl1.Refresh();//.Invalidate();
        }
        private void show_tex(object sender, EventArgs e)
        {
            if (file_2 != "" && tex == null)
            {
                if (File.Exists(file_2.Replace(".nsbmd", ".nsbtx")))
                {
                    MKDS_Course_Editor.NSBTX.nsbtx_ f = new NSBTX.nsbtx_(file_2.Replace(".nsbmd", ".nsbtx"), false);
                    f.ShowDialog();
                }
                else
                {
                    MKDS_Course_Editor.NSBTX.nsbtx_ f = new NSBTX.nsbtx_(file_2, false);
                    f.ShowDialog();
                }
            }
            
        }
        private void show_inf(object sender, EventArgs e)
        {
            NSBMDInfo i = new NSBMDInfo(nsbm);
            i.ShowDialog();
        }
        NSBTA.NSBTA.NSBTA_File ani;
        NSBTA.NSBTA.NSBTA_File ani2;
        NSBTP.NSBTP.NSBTP_File tp;
        int selectedanim = -1;
        private void nsbmd_Load(object sender, EventArgs e)
        {
			//Gl.glEnable(Gl.GL_LIGHT0);
			Gl.glEnable(Gl.GL_RESCALE_NORMAL);
			Gl.glEnable(Gl.GL_COLOR_MATERIAL);
			Gl.glEnable(Gl.GL_DEPTH_TEST);
			Gl.glEnable(Gl.GL_NORMALIZE);
			Gl.glDisable(Gl.GL_CULL_FACE);
			Gl.glFrontFace(Gl.GL_CW);
			Gl.glEnable(Gl.GL_TEXTURE_2D);
			Gl.glClearDepth(1);
			Gl.glEnable(Gl.GL_ALPHA_TEST);
			Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
			Gl.glEnable(Gl.GL_BLEND);
			Gl.glAlphaFunc(Gl.GL_GREATER, 0f);
			Gl.glClearColor(51f / 255f, 51f / 255f, 51f / 255f, 1f);
            simpleOpenGlControl1.ContextMenu = new System.Windows.Forms.ContextMenu();
            simpleOpenGlControl1.ContextMenu.MenuItems.Add("Show &Textures", new EventHandler(show_tex));
            simpleOpenGlControl1.ContextMenu.MenuItems.Add("&Info", new EventHandler(show_inf));
            MenuItem tm = new MenuItem("&Animations");
            MenuItem de = new MenuItem("&Bindpose");
            de.RadioCheck = true;
            de.Tag = -1;
            de.Checked = true;
            de.Click += new EventHandler(de_CheckedChanged);
            tm.MenuItems.Add(de);
            if (file_[0] == 76 && file_[1] == 90 && file_[2] == 55 && file_[3] == 55)
            {
                file_ = NSMBe4.ROM.LZ77_DecompressWithHeader(file_);
            }
           nsbm  = NsbmdLoader.LoadNsbmd(new MemoryStream(file_));
           t = new NsbmdGlRenderer();
           if (file_2 != "" && tex==null)
           {
               if (File.Exists(file_2.Replace(".nsbmd", ".nsbtx")) && nsbm.materials == null)
               {
                   nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(File.ReadAllBytes(file_2.Replace(".nsbmd", ".nsbtx"))),out nsbm.Textures, out nsbm.Palettes);
               }
           }
           else if (tex != null && nsbm.materials == null)
           {
               nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(tex), out nsbm.Textures, out nsbm.Palettes);
           }
           try
           {
               nsbm.MatchTextures();
           }
           catch { }
           /*if (File.Exists(file_2.Replace("course_model.nsbmd", "course_model_V.nsbmd")) && file_2 != "course_model_V.nsbmd")
           {
               nsbm2 = NsbmdLoader.LoadNsbmd(File.OpenRead(file_2.Replace("course_model.nsbmd", "course_model_V.nsbmd")));
               t2 = new NsbmdGlRenderer();
               if (file_3 != "" && nsbm2.materials == null)
               {
                   nsbm2.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(File.OpenRead(file_3.Replace("course_model.nsbtx", "course_model_V.nsbtx")));
               }
               try
               {
                   nsbm2.MatchTextures();
               }
               catch { }
           }*/
           try
           {
               if (File.Exists(file_2.Replace(".nsbmd", ".nsbca")))
               {
                   //a = (List<NsbmdAnimation>)LibNDSFormats.NSBCA.NsbcaLoader.LoadNsbca(new MemoryStream(File.ReadAllBytes(file_2.Replace(".nsbmd", ".nsbca"))));
                   ca = NSBCA.NSBCA.Read(file_2.Replace(".nsbmd", ".nsbca"));
                   timer1.Enabled = true;
                   for (int i = 0; i < ca.JAC.Length; i++)
                   {
                       MenuItem dea = new MenuItem(ca.JNT0.names[i]);
                       dea.RadioCheck = true;
                       dea.Tag = i;
                       dea.Checked = false;
                       dea.Click += new EventHandler(de_CheckedChanged);
                       tm.MenuItems.Add(dea);
                   }
               }
               else if (File.Exists(file_2.Replace(".nsbmd", "_win.nsbca")))
               {
                   ca = NSBCA.NSBCA.Read(file_2.Replace(".nsbmd", "_win.nsbca"));
                   timer1.Enabled = true;
                   for (int i = 0; i < ca.JAC.Length; i++)
                   {
                       MenuItem dea = new MenuItem(ca.JNT0.names[i]);
                       dea.RadioCheck = true;
                       dea.Tag = i;
                       dea.Checked = false;
                       dea.Click += new EventHandler(de_CheckedChanged);
                       tm.MenuItems.Add(dea);
                   }
               }
           }
           catch { }
           for (int i = 0; i < nsbm.models[0].Polygons.Count; i++)
           {
               TreeNode q = new TreeNode(nsbm.models[0].Polygons[i].Name);
               q.Checked = true;
               treeView1.Nodes.Add(q);
           }
           bool tim = false;
           if (File.Exists(file_2.Replace(".nsbmd", ".nsbta")))
           {
               ani = NSBTA.NSBTA.Read(file_2.Replace(".nsbmd", ".nsbta"));
               aniframeS = new int[ani.MAT.num_objs];
               aniframeT = new int[ani.MAT.num_objs];
               aniframeR = new int[ani.MAT.num_objs];
               aniScaleS = new int[ani.MAT.num_objs];
               aniScaleT = new int[ani.MAT.num_objs];
               tim = true;
           }
           if (File.Exists(file_2.Replace(".nsbmd", ".nsbtp")))
           {
               tp = NSBTP.NSBTP.Read(file_2.Replace(".nsbmd", ".nsbtp"));
               tim = true;
           }
           if (tim)
           {
               timer1.Enabled = true;
               timer1.Start();
           }
            simpleOpenGlControl1.ContextMenu.MenuItems.Add(tm);
            RenderFunc1(nsbm, t);
            /*if (File.Exists(file_2.Replace("course_model.nsbmd", "course_model_V.nsbta")))
            {
                ani2 = NSBTA.NSBTA.Read(file_2.Replace("course_model.nsbmd", "course_model_V.nsbta"));
                aniframeS2 = new int[ani.MAT.num_objs];
                aniframeT2 = new int[ani.MAT.num_objs];
                aniScaleS2 = new int[ani.MAT.num_objs];
                aniScaleT2 = new int[ani.MAT.num_objs];
                timer2.Enabled = true;
                timer2.Start();
            } */
        }

        void de_CheckedChanged(object sender, EventArgs e)
        {
            MenuItem a = sender as MenuItem;
            selectedanim = (int)a.Tag;
            a.Checked = true;
            for (int i = 0; i < simpleOpenGlControl1.ContextMenu.MenuItems[2].MenuItems.Count; i++)
            {
                if (simpleOpenGlControl1.ContextMenu.MenuItems[2].MenuItems[i] != a)
                {
                    simpleOpenGlControl1.ContextMenu.MenuItems[2].MenuItems[i].Checked = false;
                }
            }
        }
        public static float X = 0.0f;
        public static float Y = 0.0f;
        public static float ang = 0.0f;
        public static float dist = 0.0f;//2.5
        public static float elev = 0.0f;
        bool wrote = false;

        private void RenderFunc1(Nsbmd _nsbmd, NsbmdGlRenderer renderer)
        {
            RenderFunc1(_nsbmd, renderer, false);
        }
		private void RenderFunc1(Nsbmd _nsbmd, NsbmdGlRenderer renderer, bool anim)
		{
			//Gl.glCreateShaderObjectARB(Gl.GL_FRAGMENT_SHADER_ARB);
			//Gl.glUseProgramObjectARB(0);
			Gl.glViewport(0, 0, simpleOpenGlControl1.Width, simpleOpenGlControl1.Height);
			float aspect = (float)simpleOpenGlControl1.Width / (float)simpleOpenGlControl1.Height;//(vp[2] - vp[0]) / (vp[3] - vp[1]);
			Gl.glMatrixMode(Gl.GL_PROJECTION);
			Gl.glLoadIdentity();
			Glu.gluPerspective(90, aspect, 0.02f, 1000.0f);//0.02f, 32.0f);
			Gl.glTranslatef(X, Y, -dist);
			Gl.glRotatef(elev, 1, 0, 0);
			Gl.glRotatef(ang, 0, 1, 0);
			Gl.glMatrixMode(Gl.GL_MODELVIEW);
			Gl.glLoadIdentity();
			Gl.glTranslatef(X, Y, -dist);
			Gl.glRotatef(elev, 1, 0, 0);
			Gl.glRotatef(-ang, 0, 1, 0);
			Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
			Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
			Gl.glLightfv(Gl.GL_LIGHT2, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
			Gl.glLightfv(Gl.GL_LIGHT3, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
			Gl.glLoadIdentity();
			Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0);
			Gl.glColor3f(1.0f, 1.0f, 1.0f);
			Gl.glDepthMask(Gl.GL_TRUE);
			Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
			//try
			//{
				var mod = _nsbmd.models[0];
				if (mod == null)
					return;
				renderer.Model = _nsbmd.models[0];
				renderer.RenderModel(file_2, ani, aniframeS, aniframeT, aniScaleS, aniScaleT, aniframeR, ca, anim, selectedanim, X, Y, dist, elev, ang, licht, tp, _nsbmd);
				// t2.Model = nsbm2.models[0];
				//t2.RenderModel(file_2, ani2, aniframeS2, aniframeT2, aniScaleS2, aniScaleT2, ca);
				if (wrote == false)
				{
					//renderer.WriteOBJ(null, "C:\\model\\test.obj");
					wrote = true;
				}
			//}
			//catch (Exception ex)
			//{
			//}
		}
        /*private void RenderFunc1(Nsbmd _nsbmd, NsbmdGlRenderer renderer, bool anim)
        {

            Gl.glViewport(simpleOpenGlControl1.ClientRectangle.X,simpleOpenGlControl1.ClientRectangle.Y,simpleOpenGlControl1.ClientRectangle.Width, simpleOpenGlControl1.ClientRectangle.Height);
            //var vp = new[] { 0f, 0f, 0f, 0f };
            //Gl.glGetFloatv(Gl.GL_VIEWPORT, vp);
            float aspect = (float)simpleOpenGlControl1.Width / (float)simpleOpenGlControl1.Height;//(vp[2] - vp[0]) / (vp[3] - vp[1]);
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            Glu.gluPerspective(90, aspect, 0.02f, 1000.0f);//0.02f, 32.0f);
            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glClearDepth(1);
            //float gcd = GCD(Width, Height);

            //Gl.glFrustum(-((float)Width / gcd), ((float)Width / gcd), -((float)Height / gcd), ((float)Height / gcd), 0, 0);  // apply the projection matrix
            //Gl.glEnable(Gl.GL_DITHER);
            Gl.glEnable(Gl.GL_LINE_SMOOTH);
            Gl.glEnable(Gl.GL_POLYGON_SMOOTH);
            Gl.glEnable(Gl.GL_TEXTURE_2D);
            
            Gl.glEnable(Gl.GL_ALPHA_TEST);
            
            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glAlphaFunc(Gl.GL_GREATER, 0f);
            //Glu.gluLookAt((0.5f * Math.Cos(elev)) + X, (0.5f * Math.Sin(ang)) + Y, -dist, (0.5f * Math.Cos(elev)) + X - 50, (0.5f * Math.Sin(ang)) + Y - 50, -dist - 50, 0, 1, 0);
            Gl.glTranslatef(X, Y, -dist);
            Gl.glRotatef(elev, 1, 0, 0);
            Gl.glRotatef(ang, 0, 1, 0);
            float[] cam = new float[16];
            Gl.glGetFloatv(Gl.GL_PROJECTION_MATRIX, cam);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();
            if (true)
            {
                Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0);
                Gl.glBegin(Gl.GL_LINES);
                Gl.glColor3f(1.0f, 1.0f, 1.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(1.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 1.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 1.0f);
                Gl.glEnd();
                Gl.glRasterPos3f(1.0f, 0.0f, 0.0f);
                
                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'X');
                Gl.glRasterPos3f(0.0f, 1.0f, 0.0f);
               // Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Y');
                Gl.glRasterPos3f(0.0f, 0.0f, 1.0f);

                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Z');
            }
            Gl.glTranslatef(X, Y, -dist);
            Gl.glRotatef(elev, 1, 0, 0);
            Gl.glRotatef(-ang, 0, 1, 0);
            Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
            Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
            Gl.glLightfv(Gl.GL_LIGHT2, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
            Gl.glLightfv(Gl.GL_LIGHT3, Gl.GL_POSITION, new float[] { 1, 1, 1, 0 });
            Gl.glLoadIdentity();

            Gl.glClearColor( 51f / 255f, 51f / 255f, 51f / 255f, 1f);
            //Gl.glShadeModel(Gl.GL_SMOOTH);
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glDisable(Gl.GL_CULL_FACE);
            //Glu.GLUquadric q = Glu.gluNewQuadric();
            //Glu.gluSphere(q, 0.0201f, 50, 50);
            try
            {
                var mod = _nsbmd.models[0];
                if (mod == null)
                    return;
                renderer.Model = _nsbmd.models[0];
                renderer.RenderModel(file_2, ani, aniframeS, aniframeT, aniScaleS, aniScaleT, aniframeR,ca, anim, selectedanim, X, Y, dist, elev, ang, licht, tp, _nsbmd);
               // t2.Model = nsbm2.models[0];
                //t2.RenderModel(file_2, ani2, aniframeS2, aniframeT2, aniScaleS2, aniScaleT2, ca);
                if (wrote == false)
                {
                    //renderer.WriteOBJ(null, "C:\\model\\test.obj");
                    wrote = true;
                }
            }
            catch (Exception ex)
            {
            }
            //Gl.glMatrixMode(Gl.GL_TEXTURE);
            //Gl.glRotatef(45, 1, 0, 0);
        }*/
        // <summary> 
        /// Greatest Common Denominator (GCD). Euclidean algorithm.  
        /// </summary> 
        /// <param name="a">Width.</param> 
        /// <param name="b">Height.</param> 
        /// <returns>GCD.</returns> 
        static int GCD(int a, int b)
        {
            return b == 0 ? a : GCD(b, a % b);
        }
        private void RenderFunc1(Nsbmd _nsbmd, NsbmdGlRenderer renderer, double x, double y, double z)
        {
            Gl.glViewport(0, 0, this.Width, Height);
            var vp = new[] { 0f, 0f, 0f, 0f };
            Gl.glGetFloatv(Gl.GL_VIEWPORT, vp);
            float aspect = (vp[2] - vp[0]) / (vp[3] - vp[1]);
            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            Glu.gluPerspective(90.0f, aspect, 0.02f, 32.0f);


            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glEnable(Gl.GL_TEXTURE_2D);
            Gl.glEnable(Gl.GL_ALPHA_TEST);

            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glAlphaFunc(Gl.GL_GREATER, 0f);
            float[] cam = new float[16];
            Gl.glGetFloatv(Gl.GL_PROJECTION_MATRIX, cam);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();
            if (true)
            {
                Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0);
                Gl.glBegin(Gl.GL_LINES);
                Gl.glColor3f(1.0f, 1.0f, 1.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(1.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 1.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 0.0f);
                Gl.glVertex3f(0.0f, 0.0f, 1.0f);
                Gl.glEnd();
                Gl.glRasterPos3f(1.0f, 0.0f, 0.0f);

                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'X');
                Gl.glRasterPos3f(0.0f, 1.0f, 0.0f);
                // Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Y');
                Gl.glRasterPos3f(0.0f, 0.0f, 1.0f);

                //Glut.glutBitmapCharacter(Glut.GLUT_BITMAP_HELVETICA_18, 'Z');
            }
            Gl.glTranslatef(X, Y, -dist);
            Gl.glRotatef(elev, 1, 0, 0);
            Gl.glRotatef(ang, 0, 1, 0);
            Glu.gluLookAt(x / 500, y / 500, z / 500, (x+1) / 500, (y-5) / 500, z / 500, 0, 1, 0);
            //Gl.glClearColor(0f, 0f, 1f, 1f);
            Gl.glClearColor(Color.DarkGray.R, Color.DarkGray.G, Color.DarkGray.B, 1f);
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
            Gl.glDisable(Gl.GL_CULL_FACE);
            Glu.GLUquadric q = Glu.gluNewQuadric();
            Glu.gluSphere(q, 0.0201f, 50, 50);
            Gl.glEnable(Gl.GL_ALPHA_TEST);

            Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);
            Gl.glEnable(Gl.GL_BLEND);
            Gl.glAlphaFunc(Gl.GL_GREATER, 0f);
            try
            {

                var mod = _nsbmd.models[0];
                if (mod == null)
                    return;
                renderer.Model = _nsbmd.models[0];
                renderer.RenderModel(file_2, ani, aniframeS, aniframeT, aniScaleS, aniScaleT, aniframeR, ca, false, selectedanim, X, Y, dist, elev, ang, tp, _nsbmd);

            }
            catch (Exception ex)
            {
            }
        }
        private void simpleOpenGlControl1_KeyUp(object sender, KeyEventArgs e)
        {
            
            
        }
        

        private void simpleOpenGlControl1_Scroll(object sender, ScrollEventArgs e)
        {
           
        }

        private void simpleOpenGlControl1_Click(object sender, EventArgs e)
        {
            
        }

        private void simpleOpenGlControl1_MouseDown(object sender, MouseEventArgs e)
        {
            
        }

     
        private void simpleOpenGlControl1_KeyDown(object sender, KeyEventArgs e)
        {
            
            
        }

        private void simpleOpenGlControl1_KeyPress(object sender, KeyPressEventArgs e)
        {
            
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            
        }

        private void nsbmd_KeyDown(object sender, KeyEventArgs e)
        {
            
        }
        
        public void MatchTextures2()
        {
            for (var i = 0; i < nsbm.models.Length; i++)
            {
                for (var j = 0; j < nsbm.models[i].Materials.Count; j++)
                {
                    bool gottex = false;
                    bool gotpal = false;
                    foreach (var mat1 in nsbm.materials)
                    {
                        if (j >= nsbm.models[i].Materials.Count)
                            continue;
                        var mat2 = nsbm.models[i].Materials[j];


                        // match texture
                        if (!gottex && mat1.texname.Equals(mat2.texname))
                        {
                            Console.WriteLine("tex '{0}' matched.", mat2.texname);
                            string matname = mat2.MaterialName;
                            mat1.CopyTo(mat2);
                            mat2.MaterialName = matname;
                            gottex = true;
                        }
                        // match palette
                        if (mat2.format != 7 // NB. direct texture has no palette
                            && !gotpal
                            && (mat1.palname).Equals(mat2.palname))
                        {
                            Console.WriteLine("pal '{0}' matched.", mat1.palname);
                            mat2.palname = mat1.palname;
                            mat2.palsize = mat1.palsize;
                            mat2.paldata = mat1.paldata;
                            //mat1->palsize = 0;
                            gotpal = true;
                        }
                        try
                        {
                            for (int q = 0; q < nsbm.materials.ToArray().Length; q++)
                            {

                                if (mat2.palname.Contains(nsbm.materials.ToArray()[q].texname.Replace("nl_", "").Replace("ng_", "")) || nsbm.materials.ToArray()[q].texname.ToLower().Contains(mat2.palname.ToLower().Replace("1_2_pl", "").Replace("ods_", "").Replace("wl_", "").Replace("olg_", "").Replace("frayuka_", "").Replace("nc_", "").Replace("nt_", "").Replace("of6_", "").Replace("oc6_", "").Replace("mo_", "").Replace("nr_", "").Replace("nt_", "").Replace("_t", "").Replace("fra_", "").Replace("mo_", "").Replace("mmc_", "").Replace("pin_", "").Replace("ma_", "").Replace("ndk_", "").Replace("mhyu_", "").Replace("d_", "").Replace("de_", "").Replace("_m_pl", "").Replace("nk_", "").Replace("nd_", "").Replace("nc_", "").Replace("_3_pl", "").Replace("mtw_", "").Replace("_p3_pl", "").Replace("_pl", "").Replace("bt_", "").Replace("fra_", "").Replace("nl_", "").Replace("m_", "").Replace("ods_", "").Replace("obg_", "").Replace("mh_", "").Replace("cho_", "").Replace("ocs_", "").Replace("osf_", "").Replace("vr_", "").Replace("pt_", "").Replace("kusa_", "").Replace("la_", "").Replace("wa_", "").Replace("mbp", "bp").Replace("oc6_", "").Replace("ol6_", "").Replace("agb_", "").Replace("olg_", "").Replace("oyg_", "").Replace("mo_kanban10", "mo_kanban11").Replace("nr_", "").Replace("nt_", "").Replace(".tga", "").Replace("ng_", "").Replace("nc_", "")) || nsbm.materials.ToArray()[q].texname == mat2.palname || (nsbm.materials.ToArray()[q].texname == "ng_mariokart" && mat2.palname == "m_ma_su01_pl") || (nsbm.materials.ToArray()[q].texname == "dash01" && mat2.palname == "dash01_pl"))
                                {
                                    Console.WriteLine("tex '{0}' matched.", nsbm.materials.ToArray()[q].texname);
                                    string matname = mat2.MaterialName;
                                    nsbm.materials.ToArray()[q].CopyTo(mat2);
                                    mat2.MaterialName = matname;
                                    // mat2.palname = mat1.palname;
                                    // mat2.palsize = mat1.palsize;
                                    // mat2.paldata = mat1.paldata;
                                    //mat2.palname = nsbm.materials.ToArray()[q].palname;
                                    // mat2.palsize = nsbm.materials.ToArray()[q].palsize;
                                    // mat2.paldata = nsbm.materials.ToArray()[q].paldata;

                                    //mat2.texname = nsbm.materials.ToArray()[q].texname;
                                    //mat2.texsize = nsbm.materials.ToArray()[q].texsize;
                                    //mat2.texdata = nsbm.materials.ToArray()[q].texdata;

                                }

                            }
                            /*for (int q = 0; q < nsbm.materials.ToArray().Length; q++)
                            {

                                if (nsbm.models[0].Materials[i].format != 7 // NB. direct texture has no palette
                                    && nsbm.materials.ToList()[q].palname.Contains(mat2.texname))
                                {
                                    Console.WriteLine("pal '{0}' matched.", nsbm.materials.ToArray()[q].palname);
                                    mat2.palname = nsbm.materials.ToArray()[q].palname;
                                    mat2.palsize = nsbm.materials.ToArray()[q].palsize;
                                    mat2.paldata = nsbm.materials.ToArray()[q].paldata;
                                }

                            }*/
                        }
                        catch { }
                        nsbm.models[i].Materials[j] = mat2;
                    }
                }
            }
        }
        public void MatchTextures()
        {
            /*for (var i = 0; i < models.Length; i++)
            {
                for (var j = 0; j < models[i].Materials.Count; j++)
                {
                    bool gottex = false;
                    bool gotpal = false;
                    foreach (var mat1 in materials)
                    {
                        if (j >= models[i].Materials.Count)
                            continue;
                        var mat2 = models[i].Materials[j];


                        // match texture
                        if (!gottex && mat1.texname.Equals(mat2.texname))
                        {
                            Console.WriteLine("tex '{0}' matched.", mat2.texname);
                            mat1.CopyTo(mat2);

                            gottex = true;
                        }
                        // match palette
                        if (mat2.format != 7 // NB. direct texture has no palette
                            && !gotpal
                            && (mat1.palname).Equals(mat2.palname))
                        {
                            Console.WriteLine("pal '{0}' matched.", mat1.palname);
                            mat2.palname = mat1.palname;
                            mat2.palsize = mat1.palsize;
                            mat2.paldata = mat1.paldata;
                            //mat1->palsize = 0;
                            gotpal = true;
                        }
                    }
                }
            }*/
            nsbm.models[0].Materials.Clear();
            nsbm.models[0].Materials.AddRange(nsbm.materials);

            for (int i = 0; i < nsbm.models[0].Materials.Count; i++)
            {
                for (int q = 0; q < nsbm.materials.ToArray().Length; q++)
                {

                    if (nsbm.models[0].Materials[i].format != 7 // NB. direct texture has no palette
                        && nsbm.materials.ToList()[q].palname.Contains(nsbm.models[0].Materials[i].texname))
                    {
                        Console.WriteLine("pal '{0}' matched.", nsbm.materials.ToArray()[q].palname);
                        nsbm.models[0].Materials[i].palname = nsbm.materials.ToArray()[q].palname;
                        nsbm.models[0].Materials[i].palsize = nsbm.materials.ToArray()[q].palsize;
                        nsbm.models[0].Materials[i].paldata = nsbm.materials.ToArray()[q].paldata;                        
                    }
                }
            }
            
            /*for (var i = 0; i < nsbm.models.Length; i++)
            {
                for (var j = 0; j < nsbm.models[i].Materials.Count; j++)
                {
                    bool gottex = false;
                    bool gotpal = false;
                    foreach (var mat1 in nsbm.materials)
                    {
                        if (j >= nsbm.models[i].Materials.Count)
                            continue;
                        var mat2 = nsbm.models[i].Materials[j];

                        // match texture
                        if (!gottex && mat1.texname.Equals(mat2.texname))
                        {
                            Console.WriteLine("tex '{0}' matched.", mat2.texname);
                            mat1.CopyTo(mat2);

                            gottex = true;
                        }
                        for (int q = 0; q < nsbm.materials.ToArray().Length; q++)
                        {

                            if (mat2.format != 7 // NB. direct texture has no palette
                                && !gotpal
                                && nsbm.materials.ToList()[q].palname.Contains(mat2.texname)
                                && (mat1.palname).Equals(mat2.palname))
                            {
                                Console.WriteLine("pal '{0}' matched.", nsbm.materials.ToArray()[q].palname);
                                mat2.palname = nsbm.materials.ToArray()[q].palname;
                                mat2.palsize = nsbm.materials.ToArray()[q].palsize;
                                mat2.paldata = nsbm.materials.ToArray()[q].paldata;
                                //mat1->palsize = 0;
                                gotpal = true;
                            }
                        }
                        nsbm.models[i].Materials[j] = mat2;
                        // match palette
                        //if (mat2.format != 7 // NB. direct texture has no palette
                        //    && !gotpal
                        //    && (mat1.palname).Equals(mat2.palname))
                       // {
                        //    Console.WriteLine("pal '{0}' matched.", mat1.palname);
                        //    mat2.palname = mat1.palname;
                        //    mat2.palsize = mat1.palsize;
                       //     mat2.paldata = mat1.paldata;
                       //     //mat1->palsize = 0;
                       //     gotpal = true;
                        //}
                        // models[i].Materials[j] = mat2;
                    }
                }
            }*/
        }
        public bool wire = false;
        public bool licht = true;
        public int fix = 0;
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch(keyData)
            {
                case Keys.Right:
                    ang += 1;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.Left:
                    ang -= 1;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.Up:
                    elev += 1;
                   //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.Down:
                    elev -= 1;
                   //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.Z:
                    X -= 0.05f;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.X:
                    X += 0.05f;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.A:
                    Y -= 0.05f;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.S:
                    Y += 0.05f;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.W:
                    if (wire == false)
                    {
                        Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_LINE);
                        //simpleOpenGlControl1.Refresh();//.Invalidate();
                        RenderFunc1(nsbm, t); ;
                        simpleOpenGlControl1.Refresh();//.Invalidate();
                        wire = true;
                    }
                    else
                    {
                        Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);
                        //simpleOpenGlControl1.Refresh();//.Invalidate();
                        RenderFunc1(nsbm, t); ;
                        simpleOpenGlControl1.Refresh();//.Invalidate();
                        wire = false;
                    }
                    return true;
                case Keys.Escape:
                    X = 0.0f;
                    Y = 0.0f;
                    ang = 0.0f;
                    dist = 0.0f;
                    elev = 0.0f;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.F:
                    if (fix == 0)
                    {
                        simpleOpenGlControl1.DestroyContexts();
                        simpleOpenGlControl1.InitializeContexts();
                        simpleOpenGlControl1.Invalidate();
                        nsbm = NsbmdLoader.LoadNsbmd(new MemoryStream(file_));
                        t = new NsbmdGlRenderer();

                        if (file_2 != "" && tex == null)
                        {
                            if (File.Exists(file_2.Replace(".nsbmd", ".nsbtx")) && nsbm.materials == null)
                            {
                                nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(File.ReadAllBytes(file_2.Replace(".nsbmd", ".nsbtx"))), out nsbm.Textures, out nsbm.Palettes);
                            }
                        }
                        else if (tex != null && nsbm.materials == null)
                        {
                            nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(tex), out nsbm.Textures, out nsbm.Palettes);
                        }
                        try
                        {
                            MatchTextures();
                        }
                        catch { }
                        
                        RenderFunc1(nsbm, t);
                        fix = 1;
                    }
                    else if(fix == 1)
                    {
                        simpleOpenGlControl1.DestroyContexts();
                        simpleOpenGlControl1.InitializeContexts();
                        simpleOpenGlControl1.Invalidate();
                        nsbm = NsbmdLoader.LoadNsbmd(new MemoryStream(file_));
                        t = new NsbmdGlRenderer();

                        if (file_2 != "" && tex == null)
                        {
                            if (File.Exists(file_2.Replace(".nsbmd", ".nsbtx")) && nsbm.materials == null)
                            {
                                nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(File.ReadAllBytes(file_2.Replace(".nsbmd", ".nsbtx"))), out nsbm.Textures, out nsbm.Palettes);
                            }
                        }
                        else if (tex != null && nsbm.materials == null)
                        {
                            nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(tex), out nsbm.Textures, out nsbm.Palettes);
                        }
                        try
                        {
                            MatchTextures2();
                        }
                        catch { }
                        RenderFunc1(nsbm, t);
                        fix = 2;
                    }
                    else if(fix == 2)
                    {
                        simpleOpenGlControl1.DestroyContexts();
                        simpleOpenGlControl1.InitializeContexts();
                        simpleOpenGlControl1.Invalidate();
                        nsbm = NsbmdLoader.LoadNsbmd(new MemoryStream(file_));
                        t = new NsbmdGlRenderer();

                        if (file_2 != "" && tex == null)
                        {
                            if (File.Exists(file_2.Replace(".nsbmd", ".nsbtx")) && nsbm.materials == null)
                            {
                                nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(File.ReadAllBytes(file_2.Replace(".nsbmd", ".nsbtx"))), out nsbm.Textures, out nsbm.Palettes);
                            }
                        }
                        else if (tex != null && nsbm.materials == null)
                        {
                            nsbm.materials = LibNDSFormats.NSBTX.NsbtxLoader.LoadNsbtx(new MemoryStream(tex), out nsbm.Textures, out nsbm.Palettes);
                        }
                        try
                        {
                            nsbm.MatchTextures();
                        }
                        catch { }
                        RenderFunc1(nsbm, t);
                        fix = 0;
                    }
                    return true;
                case Keys.T:
                    elev = 90;
                    ang = 0;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                case Keys.L:
                    licht = !licht;
                    //simpleOpenGlControl1.Refresh();//.Invalidate();
                    RenderFunc1(nsbm, t); ;
                    simpleOpenGlControl1.Refresh();//.Invalidate();
                    return true;
                default:
                    return base.ProcessCmdKey(ref msg, keyData);
            }
        }

        private void simpleOpenGlControl1_Resize(object sender, EventArgs e)
        {
            //simpleOpenGlControl1.Refresh();//.Invalidate();
            RenderFunc1(nsbm, t);
            simpleOpenGlControl1.Refresh();//.Invalidate();
        }
        public void lookAt(double x, double y, double z)
        {
            //simpleOpenGlControl1.Refresh();//.Invalidate();
            RenderFunc1(nsbm, t, x, y, z);
            simpleOpenGlControl1.Refresh();//.Invalidate();
        }
        private void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            
        }
        int[] aniframeS = new int[0];
        int[] aniframeT = new int[0];
        int[] aniScaleS = new int[0];
        int[] aniScaleT = new int[0];
        int[] aniframeR = new int[0];
        int[] aniframeS2 = new int[0];
        int[] aniframeT2 = new int[0];
        int[] aniScaleS2 = new int[0];
        int[] aniScaleT2 = new int[0];
        private void timer1_Tick_1(object sender, EventArgs e)
        {
            /*for (var i = 0; i < nsbm.models[0].Polygons.Count - 1; i++)
            {
                if(ani.MAT.names[0] == nsbm.models[0].Materials[nsbm.models[0].Polygons[i].MatId].MaterialName)
                {
                    var mat = nsbm.models[0].Materials[nsbm.models[0].Polygons[i].MatId];
                    Gl.glBindTexture(Gl.GL_TEXTURE_2D, nsbm.models[0].Polygons[i].MatId+1);
                    Gl.glMatrixMode(Gl.GL_TEXTURE);
                    Gl.glLoadIdentity();
                    Gl.glScalef(0.0f / (float)mat.width, 0.0f / (float)mat.height, 0.0f);
                    Gl.glTranslated((double)ani.SRTData[0].translateS[aniframeS], 0, (double)ani.SRTData[0].translateT[aniframeT]);
                    break;
                }
            }*/
            
            //Gl.glPushMatrix();
            //Gl.glPopAttrib();
            //Gl.glMatrixMode(Gl.GL_MODELVIEW);
            //simpleOpenGlControl1.Refresh();//.Invalidate();
            RenderFunc1(nsbm, t, true);
            simpleOpenGlControl1.Refresh();//.Invalidate();
        }

        private void nsbmd_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer1.Stop();
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            //simpleOpenGlControl1.Refresh();//.Invalidate();
            RenderFunc1(nsbm, t);
            simpleOpenGlControl1.Refresh();//.Invalidate();
        }
    }
}
